/* Yet Another Experimental Software Renderer
 *
 * Copyright (c) 2010 Pawel "Hery" Dziepak
 */

#include "bmp_files.h"
#include "texture.h"
#include "utils.h"

using namespace yaesr;

color_texture *color_texture::load_bmp(const std::string &fname) {
	FILE *fp = NULL;
	fopen_s(&fp, fname.c_str(), "r");
	Verify(fp != NULL);

	bmp_header bhdr;
	fread(&bhdr, sizeof(bmp_header), 1, fp);

	if (bhdr.magic[0] != 0x42 || bhdr.magic[1] != 0x4d)
		Error("Attempt to open an incorrect BMP file.");

	dib_header dhdr;
	fread(&dhdr, sizeof(dib_header), 1, fp);

	u8 *bmp_data = new u8[dhdr.buffer_size];
	fseek(fp, bhdr.offset, SEEK_SET);
	fread(bmp_data, dhdr.buffer_size, 1, fp);
	fclose(fp);

	color_texture *tex = new color_texture(dhdr.width, dhdr.height);
	tex->data = new u32[dhdr.width * dhdr.height];

	const int byte_per_row = dhdr.buffer_size / dhdr.height;
	for (int i = 0; i < dhdr.height; i++) {
		for (int j = 0; j < dhdr.width; j++) {
			u32 value = bmp_data[i * byte_per_row + j * 3];
			value |= bmp_data[i * byte_per_row + j * 3+ 1] << 8;
			value |= bmp_data[i * byte_per_row + j * 3 + 2] << 16;
			tex->data[i * tex->width + j] = value;
		}
	}

	delete []bmp_data;

	return tex;
}

color_texture *color_texture::create(int width, int height) {
	(width);
	(height);
	return NULL;
}

color color_texture::get_pixel(int x, int y) const {
	y = max(0, y);
	x = max(0, x);
	y = min(height, y);
	x = min(width, x);
	return color::from_int32(data[y * height + x]);
}

void color_texture::put_pixel(int x, int y, color clr) {
	y = max(0, y);
	x = max(0, x);
	y = min(height, y);
	x = min(width, x);
	data[y * height + x] = clr.to_int32();
}


depth_texture *depth_texture::create(int width, int height) {
	Assert(width > 0);
	Assert(height > 0);

	depth_texture *tex = new depth_texture(width, height);
	tex->data = new double[width * height];
	for (int i = 0; i < width * height; i++)
		tex->data[i] = 1.0;

	return tex;
}

color depth_texture::get_pixel(int x, int y) const {
	Assert(x > 0);
	Assert(x < width);
	Assert(y > 0);
	Assert(y < height);

	return color(data[y * height + x]);
}

void depth_texture::put_pixel(int x, int y, color value) {
	Assert(x > 0);
	Assert(x < width);
	Assert(y > 0);
	Assert(y < height);

	data[y * height + x] = value.a;
}
